#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <iostream>
#include <sys/sendfile.h>

#include <sys/socket.h>
#include <netinet/in.h>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <netdb.h> 
#include <arpa/inet.h>

#include "send_t.hpp"

char* itoa(int,int);

void *launch_mem_function(void * obj)
{
	send_t *ptr = reinterpret_cast<send_t *>(obj);
	return ptr->send_file();
}

send_t::send_t(QString path, QString h_name)
{
	host_name = h_name;
	file_path = path;

	std::string sstr = file_path.toStdString();
	file_fd = open(sstr.c_str(), O_RDONLY);

	struct stat stat_buff;
	fstat(file_fd,&stat_buff);

	progress = new QProgressBar;
	progress->setMaximum(stat_buff.st_size);
	progress->setValue(0);

	char *ptr = ::itoa(stat_buff.st_size,10);
	QString str = file_path;
        str += " - ";
	str += ptr;
	str += " bytes";

	progress_info = new QLabel(str);
	progress_info->setWordWrap(true);
	progress_info->setAlignment(Qt::AlignCenter);
	layout = new QVBoxLayout;

	layout->addWidget(progress_info);
	layout->addWidget(progress);
	setLayout(layout);

	connect(this, SIGNAL(progress_bar(int)), progress, SLOT(setValue(int)));
	pthread_t t_rec;
	pthread_create(&t_rec, NULL, launch_mem_function, this);
}

void *send_t::send_file()
{
	void *retval = NULL;
	std::cout << "starting to read file\n";


        int sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd < 0) {
                std::cerr << "Error opening socket" << std::endl;
                return retval;
        }
        sockaddr_in serv_addr;
        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
	inet_pton(AF_INET, (host_name.toStdString()).c_str(),
		       	&serv_addr.sin_addr);
        int portno = 7171;
        serv_addr.sin_port = htons(portno);

        if(::connect(sockfd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {
                std::cerr << "ERROR connecting" << std::endl;
                return retval;
        }
	std::cout << "connected to server\n";

	::write(sockfd,file_path.toStdString().c_str(), 
			(file_path.toStdString()).length());

	///request for nex step
	char b2[1];
	::read(sockfd,b2,1);
	///sending file size
	struct stat stat_buff;
	fstat(file_fd,&stat_buff);
	::write(sockfd, &stat_buff.st_size, sizeof(off_t));

	off_t *p = NULL;
	const int SIZE = 1024;
	char buffer[SIZE];
	char b[7];
	if(::read(sockfd,b,7) == 7)
	{
		while(int n = ::read(file_fd, buffer, SIZE))
		{
			if(n>0)
			{	
				n = ::write(sockfd, buffer, n);
				this->e_progress_bar(n);
			}
			//::sendfile(sockfd,file_fd,p,SIZE);
			//this->e_progress_bar(SIZE);
			//while(::sendfile(sockfd,file_fd,p,SIZE))
			//	this->e_progress_bar(SIZE);
		}
	}
	std::cout << "   :sending finished\n";
	::close(sockfd);
	::close(file_fd);
}
void send_t::e_progress_bar(int n)
{
	static int k = 0;
	k += n;
	emit progress_bar(k);
}
